﻿using System.Windows.Forms;
using System.Drawing;
using System.Net;
using mshtml;
using System.Reflection;
using System.Runtime.InteropServices;
using System;
using System.Drawing.Drawing2D;

using Castle.Core.Logging;
using InfoGenerateSystem.Core.Utils;

namespace InfoGenerateSystem.Component
{
    [InterfaceType(1)]
    [Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")]
    public interface IHTMLElementRender2
    {
        void DrawToDC(IntPtr hdc);
        void SetDocumentPrinter(string bstrPrinterName, ref _RemotableHandle hdc);
    }

    /// <summary>
    /// 网页截图组件类
    /// 
    /// 创建人:     王昊
    /// 创建时间:   2009-04-30
    /// 
    /// </summary>
    public class WebToImageGetter
    {
        private string MyURL;
        private int Browser_Height;
        private int Browser_Width;
        private int Img_Height;
        private int Img_Width;

        public int BrowserHeight
        {
            get
            {
                return Browser_Height;
            }
            set
            {
                Browser_Height = value;
            }
        }

        public int BrowserWidth
        {
            get
            {
                return Browser_Width;
            }
            set
            {
                Browser_Width = value;
            }
        }

        public int ImageHeight
        {
            get
            {
                return Img_Height;
            }
            set
            {
                Img_Height = value;
            }
        }

        public int ImageWidth
        {
            get
            {
                return Img_Width;
            }
            set
            {
                Img_Width = value;
            }
        }

        public string WebUrl
        {
            get
            {
                return MyURL;
            }
            set
            {
                MyURL = value;
            }
        }

        public WebToImageGetter(string WebSite, int ScreenWidth, int ScreenHeight, int ImageWidth, int ImageHeight)
        {
            this.WebUrl = WebSite;
            this.BrowserHeight = ScreenHeight;
            this.BrowserWidth = ScreenWidth;
            this.ImageHeight = ImageHeight;
            this.ImageWidth = ImageWidth;
        }

        public Bitmap GetBitmap()
        {
            WebPageBitmap Shot = new WebPageBitmap(this.WebUrl, this.BrowserWidth, this.BrowserHeight);
            if (Shot.IsOk)
            {
                Shot.GetImg();
                Bitmap Pic = Shot.DrawBitmap(this.ImageWidth, this.Img_Height);
                return Pic;
            }
            else
            {
                MessageBox.Show(Shot.ErrorMessage);
            }

            return new Bitmap(100, 100);
        }
    }
    public class WebPageBitmap
    {
        private ILogger _log = ServiceHelper.GetService(typeof(ILogger)) as ILogger;

        private WebBrowser webBrowser;
        private string URL;
        private int Height;
        private int Width;
        private bool isOk;
        private string errorMessage;

        public string ErrorMessage
        {
            get { return errorMessage; }
        }

        public bool IsOk
        {
            get { return isOk; }
            set { isOk = value; }
        }

        public WebPageBitmap(string url, int width, int height)
        {
            this.Width = width;
            this.Height = height;

            this.URL =
                url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ?
                url : this.URL = "http://" + url;

            try
            // needed as the script throws an exeception if the host is not found 
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(this.URL);
                req.AllowAutoRedirect = true;
                req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
                //req.Referer = "http://www.cognifide.com";
                req.ContentType = "text/html";
                req.Accept = "*/*";
                req.KeepAlive = false;

                using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
                {
                    string x = resp.StatusDescription;
                }

            }
            catch (Exception ex)
            {
                _log.Error(ex.Message);
                _log.Error(ex.StackTrace);

                errorMessage = ex.Message;
                isOk = false;
                return;
            }
            isOk = true;
            // public, to check in program.cs if the domain is found, so the image can be saved

            webBrowser = new WebBrowser();
            webBrowser.Size = new Size(this.Width, this.Height);
            webBrowser.ScrollBarsEnabled = false;
            webBrowser.DocumentCompleted +=
            new WebBrowserDocumentCompletedEventHandler(documentCompletedEventHandler);

        }

        /// <summary> 
        /// Fetches the image 
        /// </summary> 
        /// <returns>true is the operation ended with a success </returns> 
        public bool GetImg()
        {
            try
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
                req.AllowAutoRedirect = true;
                req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
                // req.Referer = "http://www.cognifide.com";
                req.ContentType = "text/html";
                req.AllowWriteStreamBuffering = true;
                req.AutomaticDecompression = DecompressionMethods.GZip;
                req.Method = "GET";
                req.Proxy = null;
                req.ReadWriteTimeout = 20;

                HttpStatusCode status;
                using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse())
                {
                    status = resp.StatusCode;
                }

                if (status == HttpStatusCode.OK || status == HttpStatusCode.Moved)
                {
                    webBrowser.Navigate(URL);
                    while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
                    {
                        Application.DoEvents();

                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex) 
            {
                _log.Error(ex.Message);
                _log.Error(ex.StackTrace);
            }
            return false;
        }

        private void documentCompletedEventHandler(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            ((WebBrowser)sender).Document.Window.Error +=
                new HtmlElementErrorEventHandler(SuppressScriptErrorsHandler);
        }

        public void SuppressScriptErrorsHandler(object sender, HtmlElementErrorEventArgs e)
        {
            e.Handled = true;
            //MessageBox.Show("Error!");

        }

        internal Bitmap DrawBitmap(int thumbwidth, int thumbheight)
        {

            IHTMLDocument2 rawDoc = (IHTMLDocument2)webBrowser.Document.DomDocument;
            IHTMLElement rawBody = rawDoc.body;
            IHTMLElementRender2 render = (IHTMLElementRender2)rawBody;

            // the following 5 lines are auto size
            Int32 offsetWidth = rawBody.offsetWidth;
            Int32 offsetHeight = rawBody.offsetHeight;
            webBrowser.Size = new Size(offsetWidth, offsetHeight);
            Bitmap bitmap = new Bitmap(offsetWidth, offsetHeight);
            Rectangle bitmapRect = new Rectangle(0, 0, offsetWidth, offsetHeight);

            //Bitmap bitmap = new Bitmap(Width, Height);
            //Rectangle bitmapRect = new Rectangle(0, 0, Width, Height);

            // Interesting thing that despite using the renderer later 
            // this following line is still necessary or 
            // the background may not be painted on some websites. 
            webBrowser.DrawToBitmap(bitmap, bitmapRect);
            return bitmap;

            // more interesting things...lol
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                IntPtr graphicshdc = graphics.GetHdc();
                render.DrawToDC(graphicshdc);

                graphics.ReleaseHdc(graphicshdc);
                graphics.Dispose();

                if (thumbheight == Height && thumbwidth == Width)
                {
                    return bitmap;
                }
                else
                {
                    Bitmap thumbnail = new Bitmap(thumbwidth, thumbheight);
                    using (Graphics gfx = Graphics.FromImage(thumbnail))
                    {
                        // high quality image sizing 
                        gfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;                                                                      // make it look pretty 
                        gfx.DrawImage(bitmap, new Rectangle(0, 0, thumbwidth, thumbheight), bitmapRect, GraphicsUnit.Pixel);
                    }
                    bitmap.Dispose();
                    return thumbnail;
                }
            }
        }
    }
}